home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / nihcl-30.lha / nihcl-3.0 / lib / String.c < prev    next >
C/C++ Source or Header  |  1990-05-19  |  14KB  |  622 lines

  1. /* String.c -- implementation of character strings
  2.  
  3.     THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
  4.     "UNITED STATES GOVERNMENT WORK".  IT WAS WRITTEN AS A PART OF THE
  5.     AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE.  THIS MEANS IT
  6.     CANNOT BE COPYRIGHTED.  THIS SOFTWARE IS FREELY AVAILABLE TO THE
  7.     PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
  8.     RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
  9.  
  10. Authors:
  11.     C. J. Eppich and K. E. Gorlen
  12.     Bg. 12A, Rm. 2033
  13.     Computer Systems Laboratory
  14.     Division of Computer Research and Technology
  15.     National Institutes of Health
  16.     Bethesda, Maryland 20892
  17.     Phone: (301) 496-1111
  18.     uucp: uunet!nih-csl!kgorlen
  19.     Internet: kgorlen@alw.nih.gov
  20.     December, 1987
  21.  
  22. Function:
  23.     
  24. Class String implements character string objects.  Operations provided
  25. include & (concatenation) and () (substring extraction).  Type
  26. conversions between String and char* are provided, permitting the two
  27. to be used interchangeably in many contexts.  Note also that
  28. SubStrings are not derived classes from Object.
  29.  
  30. $Log:    String.c,v $
  31.  * Revision 3.0  90/05/20  00:21:32  kgorlen
  32.  * Release for 1st edition.
  33.  * 
  34. */
  35.  
  36. #include "String.h"
  37. #include "Range.h"
  38. #include "nihclconfig.h"
  39. #include "nihclIO.h"
  40. #include <ctype.h> 
  41.  
  42. #define    THIS    String
  43. #define    BASE    Object
  44.  
  45. #define BASE_CLASSES BASE::desc()
  46. #define MEMBER_CLASSES
  47. #define VIRTUAL_BASE_CLASSES Object::desc()
  48.  
  49. DEFINE_CLASS(String,1,"$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/lib/RCS/String.c,v 3.0 90/05/20 00:21:32 kgorlen Rel $",NULL,NULL);
  50.  
  51. extern const int NIHCL_BADCLASS, NIHCL_BADRANGE, NIHCL_INDEXRANGE, NIHCL_SUBSTRERR;
  52.  
  53. /* System-independent versions of toupper and tolower */
  54.  
  55. inline char to_upper(unsigned char c)    { return (islower(c) ? (c-'a'+'A') : c); }
  56. inline char to_lower(unsigned char c)    { return (isupper(c) ? (c-'A'+'a') : c); }
  57.  
  58.  
  59. //==== SubString functions:
  60.  
  61. /*
  62. The following compare functions were implemented because strncmp is
  63. not adequate for comparing character strings of unequal length.  For
  64. example, strncmp("abc","abcd",3) will return 0.
  65. */
  66.  
  67. int SubString::compare(const char* cs) const
  68. /*
  69. Return integer greater than, equal to, or less than 0, according as
  70. this SubString is lexicographically greater than, equal to, or less
  71. than cs.
  72. */
  73. {
  74.     int cl = strlen(cs);
  75.     int result = strncmp(sp,cs,sl);
  76.     if (result != 0 || sl == cl) return result;
  77.     return (sl>cl ? 1 : -1);
  78. }
  79.  
  80. int SubString::compare(const String& s) const
  81. /*
  82. Return integer greater than, equal to, or less than 0, according as
  83. this SubString is lexicographically greater than, equal to, or less
  84. than s.
  85. */
  86. {
  87.     int result = strncmp(sp,s.p,sl);
  88.     if (result != 0 || sl == s.len) return result;
  89.     return (sl>s.len ? 1 : -1);
  90. }
  91.  
  92. int SubString::compare(const SubString& ss) const
  93. /*
  94. Return integer greater than, equal to, or less than 0, according as
  95. this SubString is lexicographically greater than, equal to, or less
  96. than SubString ss.
  97. */
  98. {
  99.     int result = strncmp(sp,ss.sp,MIN(sl,ss.sl));
  100.     if (result != 0 || sl == ss.sl) return result;
  101.     return (sl>ss.sl ? 1 : -1);
  102. }
  103.  
  104. void SubString::dumpOn(ostream& strm) const
  105. // Dump this SubString on output stream strm.
  106. {
  107.     strm << String(*this);
  108.     strm << '[' << st->p << '(' << position() << ',' << sl << ")]";
  109. }
  110.  
  111. void SubString::printOn(ostream& strm) const
  112. // Print this SubString on output stream strm.
  113. {
  114.     strm << String(*this);
  115. }
  116.  
  117. void SubString::operator=(const String& s)
  118. {
  119.     if (sl == s.length()) strncpy(sp,s.p,sl);
  120.     else replace(s.p,s.len);
  121. }
  122.  
  123. void SubString::operator=(const SubString& ss)
  124. {
  125.     if (sl == ss.sl) strncpy(sp,ss.sp,sl);
  126.     else replace(ss.sp,ss.sl);
  127. }
  128.  
  129. void SubString::operator=(const char* cs)
  130. {
  131.     int cslen = strlen(cs);
  132.     if (sl == cslen) strncpy(sp,cs,sl);
  133.     else replace(cs,cslen);
  134. }
  135.  
  136. void SubString::replace(const char* src, unsigned srclen)
  137. // Replace this SubString with the argument string
  138. // Terminology:
  139. //    head: portion of destination string before this SubString
  140. //    tail: portion of destination string after this SubString
  141. {
  142. #ifdef DEBUG
  143. cerr << "replacing " << *this << " by ";
  144. cerr.write(src, srclen);
  145. cerr << " ...\n";
  146. #endif
  147.     bool overlap = NO;    // src overlaps destination String
  148.     int tailDelta = 0;    // amount to adjust for tail movement
  149.     char* srcbuf = 0;    // buffer to hold src if it overlaps SubString
  150. // src overlap destination String?
  151.     if (src >= st->p && src <= st->p+st->len) {
  152.         overlap = YES;    // src overlaps destination String
  153. // src overlap only tail of destination String?
  154.         if (src >= sp+sl) tailDelta = srclen-sl;
  155.         else {        
  156. // src overlap this SubString?
  157.             if (src+srclen > sp) {    // move src to buffer
  158.                 srcbuf = new char[srclen];
  159.                 strncpy(srcbuf,src,srclen);
  160.                 src = srcbuf;
  161.                 overlap = NO;    // no overlap now
  162.             }
  163.         }
  164.     }
  165. #ifdef DEBUG
  166. cerr << "overlap=" << overlap << "  tailDelta=" << tailDelta << "  srcbuf=" << (int)srcbuf << '\n';
  167. #endif
  168.     if (srclen+st->len >= sl+st->alloc) {    // need to make String bigger
  169.         char* p = st->p;
  170.         st->alloc = st->len+srclen-sl+DEFAULT_STRING_EXTRA+1;
  171.         st->p = (char*)realloc(st->p, st->alloc);
  172.         sp += st->p-p;
  173.         if (overlap) src += st->p-p;
  174. #ifdef DEBUG
  175. cerr << "realloc(" << st->alloc << ")  " << *this << '\n';
  176. #endif
  177.     }
  178.     if (sl > srclen) {    // shift tail down
  179.         register const char* p = sp+sl;
  180.         register char* q = sp+srclen;
  181.         while (*q++ = *p++);
  182.     }
  183.     else {            // shift tail up
  184.         register const char* p = st->p+st->len;
  185.         register char* q = (char*)p+srclen-sl;
  186.         register unsigned n = p-(sp+sl)+1;
  187.         while (n--) *q-- = *p--;
  188.     }
  189.     src += tailDelta;
  190.     st->len += srclen-sl;
  191. #ifdef DEBUG
  192. cerr << "target " << *this << " source ";
  193. cerr.write(src, srclen);
  194. cerr << endl;
  195. #endif
  196.     strncpy(sp,src,srclen);        // insert src into destination
  197.     if (srcbuf) free(srcbuf);
  198. #ifdef DEBUG
  199. cerr << "... result: " << *this << '\n';
  200. #endif
  201. }
  202.  
  203. String SubString::operator&(const SubString& ss) const
  204. {
  205.     String t(sl + ss.sl);
  206.     strncpy (t.p, sp, sl);
  207.     strncpy (&(t.p[sl]), ss.sp, ss.sl);
  208.     t.len = sl + ss.sl;
  209.     t.p[t.len] = '\0';
  210.     return t;
  211. }
  212.  
  213. String SubString::operator&(const String& s) const
  214. {
  215.     String t(sl + s.alloc -1);
  216.     strncpy(t.p, sp, sl);
  217.     strcpy(&(t.p[sl]), s.p);
  218.     t.len = sl + s.len;
  219.     return t;
  220. }
  221.  
  222. String SubString::operator&(const char* cs) const
  223. {
  224.     int cslen = strlen(cs);
  225.     String t(sl + cslen);
  226.     strncpy(t.p,sp,sl);
  227.     strcpy(&(t.p[sl]),cs);
  228.     t.len = sl + cslen;
  229.     return t;
  230. }
  231.  
  232. String operator&(const char* cs, const SubString& ss)
  233. {
  234.     unsigned cslen = strlen(cs);
  235.     String t(cslen + ss.sl);
  236.     strcpy(t.p,cs);
  237.     strncpy(&(t.p[cslen]),ss.sp,ss.sl);
  238.     t.len = cslen + ss.sl;
  239.     t.p[t.len] = '\0';
  240.     return t;
  241. }
  242.  
  243. void SubString::checkSubStr() const
  244. // check for legal SubString
  245. {
  246.     unsigned pos = position();
  247.     unsigned len = st->len;
  248.     if (pos+sl <= len) return;
  249.     if (sl == 0 && pos == len) return;
  250.     setError(NIHCL_SUBSTRERR,DEFAULT,st,st->className(),pos,sl);
  251. }
  252.  
  253. //==== String Private functions:
  254.  
  255. void String::indexRangeErr() const
  256. {
  257.     setError(NIHCL_INDEXRANGE,DEFAULT,this,className());
  258. }
  259.  
  260. //==== String Constructors:
  261.  
  262. String::String(const char& c, unsigned l, unsigned extra)
  263. {
  264.     len = l;
  265.     alloc = len + extra + 1;
  266.     p = (char*)malloc(alloc);
  267.     register unsigned i=len;
  268.     p[i] = '\0';
  269.     while (i > 0) p[--i] = c;
  270. }
  271.  
  272. String::String()
  273. {
  274.     len = 0;
  275.     alloc = DEFAULT_STRING_EXTRA + 1;
  276.     p = (char*)malloc(alloc);
  277.     *p = '\0';
  278. }
  279.  
  280. String::String(unsigned extra)
  281. {
  282.     len = 0;
  283.     alloc = extra + 1;
  284.     p = (char*)malloc(alloc);
  285.     *p = '\0';
  286. }
  287.  
  288. String::String(const char* cs)
  289.     len = strlen(cs);
  290.     alloc = len + DEFAULT_STRING_EXTRA + 1;
  291.     p = (char*)malloc(alloc);
  292.       strcpy(p,cs); 
  293. }
  294.  
  295. String::String(const char* cs, unsigned extra)
  296.     len = strlen(cs);
  297.     alloc = len + extra + 1;
  298.     p = (char*)malloc(alloc);
  299.       strcpy(p,cs); 
  300. }
  301.  
  302. String::String(const String& s)
  303. {
  304.     len = s.len;
  305.     alloc = len + DEFAULT_STRING_EXTRA + 1;
  306.     p = (char*)malloc(alloc);
  307.     strcpy (p,s.p);
  308. }
  309.  
  310. String::String(const String& s, unsigned extra)
  311. {
  312.     len = s.len;
  313.     alloc = len + extra + 1;
  314.     p = (char*)malloc(alloc);
  315.     strcpy(p,s.p);
  316. }
  317.  
  318. String::String(const SubString& ss)
  319. {
  320.     len = ss.sl;
  321.     alloc = len + DEFAULT_STRING_EXTRA + 1;
  322.     p = (char*)malloc(alloc);
  323.     strncpy(p,ss.sp,ss.sl);
  324.     p[len] = '\0';
  325. }
  326.  
  327. String::String(const SubString& ss, unsigned extra)
  328. {
  329.     len = ss.sl;
  330.     alloc = len + extra + 1;
  331.     p = (char*)malloc(alloc);
  332.     strncpy(p,ss.sp,ss.sl);
  333.     p[len] = '\0';
  334. }
  335.  
  336. String::~String()    { free(p); }
  337.  
  338. //==== Operators:
  339.  
  340. SubString String::operator()(const Range& r)
  341. {
  342.     if (r.valid()) return SubString(*this,r.firstIndex(),r.length());
  343.     else  setError(NIHCL_BADRANGE,DEFAULT,this,className(),"operator()",r.firstIndex(),r.length());
  344. }
  345.  
  346. const SubString String::operator()(const Range& r) const
  347. {
  348.     if (r.valid()) return SubString(*this,r.firstIndex(),r.length());
  349.     else  setError(NIHCL_BADRANGE,DEFAULT,this,className(),"operator()",r.firstIndex(),r.length());
  350. }
  351.  
  352. void String::operator=(const String& s)
  353. {
  354.     if (p == s.p) return;
  355.     len = s.len;
  356.     if (len >= alloc) {
  357.         free(p);
  358.         p = (char*)malloc(alloc = s.alloc);
  359.     }
  360.     strcpy(p,s.p);
  361. }
  362.  
  363. void String::operator=(const SubString& ss)
  364. {
  365.     len = ss.sl;
  366.     if (this == ss.st) {        // s = s(pos,len)
  367.         if (ss.sp == p) {    // s = s(0,len)
  368.             p[len] = '\0';
  369.             return;
  370.         }
  371.         register const char* src = ss.sp;
  372.         register char* dst = p;
  373.         register unsigned n = len;
  374.         while (n--) *dst++ = *src++;
  375.         *dst = '\0';
  376.         return;
  377.     }
  378.     else if (len >= alloc) {
  379.         alloc = ss.sl + DEFAULT_STRING_EXTRA + 1;
  380.         free(p);
  381.         p = (char*)malloc(alloc);
  382.     }
  383.     strncpy(p, ss.sp, ss.sl);
  384.     p[len] = '\0';
  385. }
  386.  
  387. void String::operator=(const char* cs)
  388. {
  389.     len = strlen(cs);
  390.     if (len >= alloc) {
  391.         alloc = len + DEFAULT_STRING_EXTRA + 1;
  392.         free(p);
  393.         p = (char*)malloc(alloc);
  394.     }    
  395.     strcpy(p,cs);
  396. }
  397.  
  398. String String::operator&(const String& s) const
  399. {
  400.     String t(len+s.len);
  401.     strcpy(t.p,p);
  402.     strcpy(&(t.p[len]), s.p);
  403.     t.len = len+s.len;
  404.     return t;
  405. }
  406.  
  407. String String::operator&(const SubString& ss) const
  408. {
  409.     String t(len+ss.sl);
  410.     strcpy(t.p,p);
  411.     strncpy(&(t.p[len]), ss.sp, ss.sl);
  412.     t.len = len+ss.sl;
  413.     t.p[t.len] = '\0';
  414.     return t;
  415. }
  416.  
  417. String String::operator&(const char* cs) const
  418. {
  419.     unsigned cslen = strlen(cs);
  420.     String t(len+cslen);
  421.     strcpy (t.p,p);
  422.     strcpy (&(t.p[len]), cs);
  423.     t.len = len+cslen;
  424.     return t;
  425. }
  426.  
  427. String operator&(const char* cs, const String& s)
  428. {
  429.     int cslen=strlen(cs);
  430.     String t(cslen + s.len);
  431.     strcpy(t.p,cs);
  432.     strcpy(&(t.p[cslen]),s.p);
  433.     t.len = cslen + s.len;
  434.     return t;
  435. }
  436.  
  437. String& String::operator&=(const String& s)
  438. // Concatenate a String with another
  439. {
  440.     if (alloc <= len + s.len) {
  441.         alloc += s.len + DEFAULT_STRING_EXTRA;
  442.         p = (char*)realloc(p, alloc);
  443.     }
  444.     strcpy(&p[len],s.p);
  445.     len += s.len;
  446.     return *this;
  447. }    
  448.  
  449. String& String::operator&=(const SubString& ss)
  450. {
  451.     if (alloc <= len + ss.sl) {
  452.         alloc += ss.sl + DEFAULT_STRING_EXTRA;
  453.         if (this == ss.st) {    // s &= s(pos,len)
  454.             char* t = p;
  455.             p = (char*)malloc(alloc);
  456.             strcpy(p,t);
  457.             strncpy(&(p[len]),ss.sp,ss.sl);
  458.             free(t);
  459.             len += ss.sl;
  460.             p[len] = '\0';
  461.             return *this;
  462.         }
  463.         else p = (char*)realloc(p,alloc);
  464.     }        
  465.     strncpy(&(p[len]),ss.sp,ss.sl);
  466.     len += ss.sl;
  467.     p[len] = '\0';
  468.     return *this;
  469. }
  470.  
  471. String& String::operator&=(const char* cs)
  472. {
  473.     int cslen = strlen(cs);
  474.     if (alloc <= len + cslen) {
  475.         alloc += cslen + DEFAULT_STRING_EXTRA;
  476.         p = (char*)realloc(p,alloc);
  477.     }
  478.     strcpy(&(p[len]),cs);
  479.     len += cslen;
  480.     return *this;
  481. }
  482.  
  483. void String::toAscii()
  484. {
  485.     register unsigned i = len;
  486.     register char* q = p;
  487.     while (i--) { *q = toascii(*q); q++; }
  488. }
  489.  
  490. void String::toLower()
  491. {
  492.     register unsigned i = len;
  493.     register char* q = p;
  494.     while (i--) { *q = to_lower(*q); q++; }
  495. }
  496.  
  497. void String::toUpper()
  498. {
  499.     register unsigned i = len;
  500.     register char* q = p;
  501.     while (i--) { *q = to_upper(*q); q++; }
  502. }
  503.  
  504. int String::compare(const Object& ob) const
  505. {
  506.     assertArgClass(ob,classDesc,"compare");
  507.     return strcmp(p,castdown(ob).p);
  508. }
  509.  
  510. void String::deepenShallowCopy() {}
  511.  
  512. static union char_mask {
  513.     unsigned in[sizeof(int)];
  514.     char ch[sizeof(int)*sizeof(int)];
  515.     char_mask();
  516. } mask;
  517.  
  518. char_mask::char_mask()
  519. {
  520.     for (register unsigned i=0; i<sizeof(int); i++) {
  521.         for (register unsigned j=0; j<sizeof(int); j++) ch[sizeof(int)*i+j] = j<i ? 0xff : 0;
  522.     }
  523. }
  524.  
  525. bool String::operator==(const String& s) const
  526. {
  527.     if (len != s.len) return NO;
  528.     register unsigned i = div_sizeof_int(len);
  529.     register const unsigned* q = (unsigned*)p;
  530.     register const unsigned* r = (unsigned*)s.p;
  531.     while (i--) if (*q++ != *r++) return NO;
  532.     if ((i = mod_sizeof_int(len)) != 0)
  533.         if ((*q & mask.in[i]) != (*r & mask.in[i])) return NO;
  534.     return YES;
  535. }
  536.  
  537. unsigned String::hash() const
  538. {
  539.     register unsigned h = len;
  540.     register unsigned i = div_sizeof_int(len);
  541.     register unsigned* q = (unsigned*)p;
  542.     while (i--) h ^= *q++;
  543.     if ((i = mod_sizeof_int(len)) != 0)
  544.         h ^= *q & mask.in[i];
  545.     return h;
  546. }
  547.  
  548. bool String::isEqual(const Object& a) const
  549. {
  550.     return a.isSpecies(classDesc) && *this==castdown(a);
  551. }
  552.  
  553. void String::printOn(ostream& strm) const    { strm << p; }
  554.  
  555. void String::scanFrom(istream& strm)
  556. //    Read next line of input from strm into this String.
  557. {
  558.     ostream* os = strm.tie((ostream*)0);
  559.     if (os != 0) {
  560.         os->flush();
  561.         strm.tie(os);
  562.     }
  563.     char c;
  564.     strm.get(c);
  565.     if (c != '\n') strm.putback(c);
  566.     char temp[513];
  567.     strm.get(temp,513);
  568.     *this = String(temp);
  569. }
  570.  
  571. unsigned String::reSize(unsigned new_capacity)
  572. {
  573.     if (new_capacity < len) new_capacity = len;
  574.     if (alloc != new_capacity+1) {
  575.         p = (char*)realloc(p,alloc = new_capacity+1);
  576.     }
  577.     return alloc - 1;
  578. }
  579.  
  580. unsigned String::size() const        { return len; }
  581.  
  582. unsigned String::capacity() const    { return alloc - 1; }
  583.  
  584. const Class* String::species() const
  585. {
  586.     return String::desc();
  587. }
  588.  
  589. String::String(OIOifd& fd)
  590.     : BASE(fd)
  591. {
  592.     fd >> len >> alloc;
  593.     p = (char*)malloc(alloc);
  594.     fd.get(p,len+1);
  595. }
  596.  
  597. void String::storer(OIOofd& fd) const
  598. {
  599.     BASE::storer(fd);
  600.     fd << len << alloc;
  601.     fd.put(p,len+1);    // store terminating null character
  602. }
  603.  
  604. String::String(OIOin& strm)
  605.     : BASE(strm)
  606. {
  607.     strm >> len >> alloc;
  608.     p = (char*)malloc(alloc);
  609.     strm.getCString(p,len+1);
  610. }
  611.  
  612. void String::storer(OIOout& strm) const
  613. {
  614.     BASE::storer(strm);
  615.     strm << len << alloc;
  616.     strm.putCString(p);
  617. }
  618.  
  619.  
  620.